<template name="qcToast">
  <view v-show="innerData.visible" :style="`z-index:${innerData.zIndex};position:fixed;`">
    <view @click="click" class="hd-toast">
      <view class="title">
        {{ innerData.title }}
      </view>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, watch, inject } from 'vue';
import { defaultToastOptions, toastDefaultKey, toastDefaultOptionKey } from './index';
import isDef from './util';
import type { ToastOptions } from './types';

interface Props {
  // toast是否展示
  visible?: boolean;
  /**
   * toast展示时长(ms)，值为 0 时，toast 不会消失，默认值1500
   */
  duration?: number;

  /**
   * toast提示的内容
   */
  title?: string;
  /**
   * toast图标
   * - success: 显示成功图标
   * - warning: 显示警告图标
   * - error: 显示错误图标
   * - none: 不显示图标
   */
  icon?: 'success' | 'warning' | 'error' | 'none';
  // 自定义层级，默认值 1000
  zIndex?: number;
  // toast唯一标识
  id?: string;
}

let props = withDefaults(defineProps<Props>(), {
  visible: false,
  duration: 1500,
  title: '',
  icon: 'none',
  zIndex: 1000,
  id: '',
});

let innerData = ref<Props>({
  visible: false,
  duration: 1500,
  title: '',
  icon: 'none',
  zIndex: 1000,
});

const emit = defineEmits(['update:visible', 'click']);
const toastKey = props.id ? '__TOAST__' + props.id : toastDefaultKey;
const toastOptionKey = props.id ? '__TOAST_OPTION__' + props.id : toastDefaultOptionKey;
const toastShow = inject(toastKey) || ref<boolean>(false); // 是否展示toast组件
const toastOption = inject(toastOptionKey) || ref<ToastOptions>(defaultToastOptions); // toast选项

// 监听options变化展示
watch(
  () => toastOption.value,
  (newVal: ToastOptions) => {
    reset(newVal);
  }
);

// 监听是否visible
watch([() => props.visible, () => toastShow.value], () => {
  if (props.visible || toastShow.value) {
    show();
  } else {
    hide();
  }
});

// 定时器
let timer = ref<any>(null);

// 打开
function show() {
  timer.value && clearTimeout(timer.value);
  innerData.value.visible = true;
  /**
   * 消息展示状态变更时触发
   * @arg value:Boolean 消息展示状态，建议通过v-model双向绑定输入值，而不是监听此事件的形式
   */
  emit('update:visible', true);
  if (innerData.value.duration && innerData.value.duration !== Infinity) {
    timer.value = setTimeout(() => {
      clearTimeout(timer.value);
      hide();
    }, innerData.value.duration);
  }
}

// 关闭
function hide() {
  if (innerData.value.visible) {
    emit('update:visible', false);
    innerData.value.visible = false;
    toastShow.value = false;
    timer.value && clearTimeout(timer.value);
  }
}

/**
 * 重置toast选项值
 * @param option toast选项值
 */
function reset(option: ToastOptions) {
  if (option) {
    innerData.value = {
      visible: false,
      duration: isDef(option.duration) ? option.duration! : props.duration,
      title: isDef(option.title) ? option.title! : props.title,
      icon: isDef(option.icon) ? option.icon! : props.icon,
      zIndex: isDef(option.zIndex) ? option.zIndex! : props.zIndex,
    };
  }
}

//  被点击
function click() {
  emit('click');
}
</script>

<style lang="scss" scoped>
.hd-toast {
  position: fixed;
  z-index: 10001;
  display: inline-block;
  max-width: 420rpx;
  width: fit-content;
  box-sizing: border-box;
  // padding: 24rpx 52rpx;
  padding: 24rpx 52rpx;
  top: 50vh;
  left: 0;
  right: 0;
  margin: 0 auto;
  transform: translateY(-50%);
  border-radius: 16rpx;
  color: #fff;
  background-color: rgba(0, 0, 0, 0.7);
  .title {
    line-height: 36rpx;
    text-align: center;
    font-size: 26rpx;
    max-height: 70vh;
    overflow: auto;
  }
}
</style>
